#include "PreCompiled.h"
#include "Console.h"
#include "Document_Gui.h"
#include "MainWindow.h"
#include "View3DInventor.h"
#include "VIewWindow.h"
#include "ViewProvider.h"
#include "viewProviderDocumentObject.h"
#include "DocumentObject.h"
#include "CommandHandler.h"
#include "FileDialog.h"
#include "Application_App.h"
using namespace App;
using namespace Gui;
struct DocumentP
{
	//Thumbnail thumb;
	int        _iWinCount;
	int        _iDocId;
	bool       _isClosing;
	bool       _isModified;
	ViewProvider*   _pcInEdit;
	Application*    _pcAppWnd;
	// the doc/Document
	Document_App*  _pcDocument;
	/// List of all registered views
	std::list<BaseView*> baseViews;
	/// List of all registered views
	std::list<BaseView*> passiveViews;
	std::map<const App::DocumentObject*,ViewProviderDocumentObject*> _ViewProviderMap;
	std::map<std::string,ViewProvider*> _ViewProviderMapAnnotation;

	typedef boost::signals::connection Connection;
	Connection connectNewObject;
	Connection connectDelObject;
	Connection connectCngObject;
	Connection connectRenObject;
	Connection connectActObject;
	Connection connectSaveDocument;
	Connection connectRestDocument;
	Connection connectStartLoadDocument;
	Connection connectFinishLoadDocument;
};
Document_Gui::Document_Gui(Document_App* pcDocument,Application* app)
{
	d = new struct DocumentP;
	d->_iWinCount = 1;
	// new instance
	d->_iDocId = 0;
	d->_isClosing = false;
	d->_isModified = false;
	d->_pcAppWnd = app;
	d->_pcDocument = pcDocument;
	d->_pcInEdit = 0;

	d->connectNewObject = pcDocument->signalNewObject.connect(boost::BOOST_BIND(&Document_Gui::slotNewObject,this,_1));

} 

Document_Gui::~Document_Gui(void)
{
}
void Document_Gui::createView(const char* sType)
{
   View3DInventor* view3D = new View3DInventor(this,getMainWindow());
   view3D->setWindowTitle("viewTitle");
  // view3D->setWindowModified(true);
   view3D->setWindowIcon(QApplication::windowIcon());
   //view3D->resize(400, 300);
   getMainWindow()->addWindow(view3D);

}



void Document_Gui::attachView(BaseView* pcView,bool bpassiv)
{

}
void Document_Gui::detachView(BaseView* pcView,bool bpassiv)
{

}
void Document_Gui::slotNewObject(const App::DocumentObject& obj)
{
	std::string cName = obj.getViewProviderName();

	if(cName.empty())
	{
		Base::Console().Error("%s has no view provider specified\n",obj.getTypeId().getName());
	    return;
	}

	Base::BaseClass* base = static_cast<Base::BaseClass*>(Base::Type::createInstanceByName(cName.c_str(),true));
	if(base)
	{
		assert(base->getTypeId().isDerivedFrom(Gui::ViewProviderDocumentObject::getClassTypeId()));

		ViewProviderDocumentObject* pcProvider = static_cast<ViewProviderDocumentObject*>(base);

		d->_ViewProviderMap[&obj] = pcProvider;

		pcProvider->attach(const_cast<App::DocumentObject*>(&obj));

	    signalNewObject(*pcProvider);
	}
}

Document_App* Document_Gui::getDocument()const
{
    return d->_pcDocument; 
}
Gui::ViewProvider* Document_Gui::getViewProvider(const App::DocumentObject* pobject)const
{
	std::map<const App::DocumentObject*,Gui::ViewProviderDocumentObject*>::const_iterator
		it = d->_ViewProviderMap.find( pobject );
	return ( (it != d->_ViewProviderMap.end()) ? it->second : 0 );

}
bool Document_Gui::canClose()
{
   return true;
}
bool Document_Gui::isLastView()
{
	return true;
}
ViewWindow* Document_Gui::getActiveView()const
{
	return NULL;
}
unsigned int Document_Gui::getMemSize (void) const
{
   unsigned int size = 0;
   return size;
}

bool Document_Gui::save()
{ 
	if(d->_pcDocument->isSaved())
	CommandHandlerManager::getSingleton()->excuteCommandByName("SaveFileCommand");
	else
		return saveAs();

}
bool Document_Gui::saveAs()
{
	getMainWindow()->showMessage(QObject::tr("Save document under new filename..."));

	QString exe = qApp->applicationName();
	QString fn = QFileDialog::getSaveFileName(getMainWindow(), QObject::tr("Save %1 Document").arg(exe), 
		0, QObject::tr("%1 document (*.FCStd)").arg(exe));
	if (!fn.isEmpty()) {
		//FileDialog::setWorkingDirectory(fn);
		QString file = fn.toLower();
		if (!file.endsWith(QLatin1String(".fcstd"))) {
			fn += QLatin1String(".fcstd");
			QFileInfo fi;
			fi.setFile(fn);
			if (fi.exists()) {
				// if we auto-append the extension make sure that we don't override an existing file
				int ret = QMessageBox::question(getMainWindow(), QObject::tr("Save As"), 
					QObject::tr("%1 already exists.\n"
					"Do you want to replace it?").arg(fn),
					QMessageBox::Yes|QMessageBox::Default,
					QMessageBox::No|QMessageBox::Escape); 
				if (ret != QMessageBox::Yes)
					fn = QString();
			}
		}
	}

	if (!fn.isEmpty()) {
 		QFileInfo fi;
 		fi.setFile(fn);
 		QString bn = fi.baseName();
 
 		//const char * DocName = GetApplication().getDocumentName(getDocument());
		CommandHandlerManager::getSingleton()->excuteCommandByName("setFileNameCommand",fn.toAscii());
		CommandHandlerManager::getSingleton()->excuteCommandByName("setLabelCommand",bn.toAscii());
		CommandHandlerManager::getSingleton()->excuteCommandByName("SaveFileCommand");
 		//setModified(false);
// 
// 		getMainWindow()->appendRecentFile(fi.filePath());
		return true;
	}
	else {
		getMainWindow()->showMessage(QObject::tr("Saving aborted"), 2000);
		return false;
	}
}
/// This method is used to save properties or very small amounts of data to an XML document.
void Document_Gui::Save (Base::Writer &writer) const
{
}
/// This method is used to restore properties from an XML document.
void Document_Gui::Restore(Base::XMLReader &reader)
{

}
/// This method is used to save large amounts of data to a binary file.
void Document_Gui::SaveDocFile (Base::Writer &writer) const
{

}
/// This method is used to restore large amounts of data from a binary file.
void Document_Gui::RestoreDocFile(Base::Reader &reader)
{

}
